#include "TextView.h"
#include "lang/String.h"
#include "lang/StringBuilder.h"
#include "array/Array.hpp"
#include "lang/Math.h"
using namespace yzrilyzr_util;
using namespace yzrilyzr_lang;
namespace yzrilyzr_simplecanvas{
	// 判断字符是否是单词的一部分
	static bool isWord(char c){
		return (c >= 'A' && c <= 'Z') ||
			(c >= 'a' && c <= 'z') ||
			(c >= '0' && c <= '9');
	}
	TextView::TextView(){
		font.setTypeface(Theme::getDefaultTypeface());
		font.setSize(px(14)); // 默认字体大小
		textColor=SK_ColorBLACK;
	}

	void TextView::onMeasure(MeasureSpec & widthMeasureSpec, MeasureSpec & heightMeasureSpec){
		if(getFinalVisibility() == GONE){
			setMeasuredDimension(0, 0);
			return;
		}

		double mW=0, mH=0;
		double lineH=font.getSize();
		double padW=getPadding().left + getPadding().right;
		double padH=getPadding().top + getPadding().bottom;

		// 宽度测量
		if(widthMeasureSpec.mode == MeasureSpec::EXACTLY){
			mW=widthMeasureSpec.size - padW;
		} else if(widthMeasureSpec.mode == MeasureSpec::AT_MOST){
			// 测量文本宽度
			SkRect bounds;
			font.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8, &bounds);
			mW=Math::min((double)bounds.width(), widthMeasureSpec.size - padW);
		} else{ // UNSPECIFIED
			SkRect bounds;
			font.measureText(text.c_str(), text.length(), SkTextEncoding::kUTF8, &bounds);
			mW=bounds.width();
		}

		// 高度测量
		if(heightMeasureSpec.mode == MeasureSpec::EXACTLY){
			mH=heightMeasureSpec.size - padH;
		} else if(heightMeasureSpec.mode == MeasureSpec::AT_MOST){
			// 计算行高
			int lineCount=1; // 简单实现，不考虑换行
			mH=Math::min(lineCount * lineH, heightMeasureSpec.size - padH);
		} else{ // UNSPECIFIED
			mH=lineH; // 单行高度
		}
		splitText(getText(), mW);

		setMeasuredDimension(mW + padW, mH + padH);
	}

	void TextView::setText(const std::string & str){
		text=str;
		requestLayout();
		invalidate();
	}

	const std::string & TextView::getText() const{
		return text;
	}

	void TextView::setTextSize(float size){
		font.setSize(size);
		requestLayout();
		invalidate();
	}

	void TextView::setTextColor(SkColor color){
		textColor=color;
		invalidate();
	}

	void TextView::onDraw(SkCanvas & canvas){
		if(getFinalVisibility() != VISIBLE) return;

		View::onDraw(canvas); // 先绘制背景等

		SkPaint paint;
		paint.setAntiAlias(true);
		paint.setColor(isEnabled()?textColor:Theme::getDefaultDisabledColor());

		SkFontMetrics metrics;
		font.getMetrics(&metrics);
		float firstLineBaseline=-metrics.fAscent;
		float lineHeight=metrics.fDescent - metrics.fAscent + metrics.fLeading;
		// 绘制文本
		float x=getPadding().left;
		float y=getPadding().top + firstLineBaseline; // 基线位置

		if(!splited.empty()){
			for(u_index i=0; i < splited.size(); i++){
				std::string & str=splited[i];
				canvas.drawSimpleText(str.c_str(), str.length(),
									  SkTextEncoding::kUTF8, x, y,
									  font, paint);
				y+=lineHeight;
			}
		}
	}

	// 测量文本宽度
	float TextView::measureText(const String & s, u_index end){
		if(end > s.length()){
			end=s.length();
		}
		std::string str2=s.substring(0, end).tostring();
		SkRect bounds;
		font.measureText(str2.c_str(), str2.length(), SkTextEncoding::kUTF8, &bounds);
		return bounds.width();
	}

	// 分割文本为多行
	void TextView::splitText(const String & lorem, float wLimit){
		splited.clear();
		auto splm=lorem.split("\n");
		for(String &a : splm){
			splitLine(a, wLimit);
		}
	}

	// 分割单行文本
	void TextView::splitLine(const String & line, float wLimit){
		StringBuilder remaining=line;
		while(remaining.length() > 0){
			int fine=getSplitIndexFine(wLimit, remaining);
			if(fine > remaining.length()) fine=remaining.length();

			fine=getSplitPoint(remaining, fine);
			splited.push_back(remaining.substring(0, fine).tostring());
			remaining.deleteRange(0, fine);
		}
	}

	// 使用二分查找找到合适的分割点
	int TextView::getSplitIndexFine(float wLimit, const String & input){
		float w=-1;
		int max=input.length();
		int min=0;
		int mid=(max + min) / 2;

		while(w != wLimit && max >= min){
			w=measureText(input, mid);
			if(w > wLimit){
				max=mid - 1;
			} else if(w < wLimit){
				min=mid + 1;
			}
			mid=(min + max) / 2;
		}

		if(mid < 0) mid=0;
		if(mid > input.length()) mid=input.length();
		return mid;
	}

	// 找到合适的分割位置（不在单词中间分割）
	int TextView::getSplitPoint(const String & input, int index){
		if(index >= input.length() || index - 1 < 0){
			return index;
		}

		int srcIndex=index;
		char c1=input[index - 1];
		char c2=input[index];
		bool w1=isWord(c1);
		bool w2=isWord(c2);

		while(w1 && w2){
			index--;
			if(index - 1 < 0){
				return srcIndex;
			}
			c1=input[index - 1];
			c2=input[index];
			w1=isWord(c1);
			w2=isWord(c2);
		}

		return index;
	}
}